package cn.xshi.oauth.web;

import cn.xshi.oauth.model.*;
import cn.xshi.oauth.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import cn.xshi.common.annotation.Auth;
import cn.xshi.common.base.BaseAction;
import cn.xshi.common.base.BaseHttpSessionEntity;
import cn.xshi.common.base.BaseResult;
import cn.xshi.common.constant.SessionConstant;
import cn.xshi.common.entity.LoginEntity;
import cn.xshi.common.entity.OauthAccountEntity;
import cn.xshi.common.util.MD5;
import cn.xshi.common.session.HttpSessionUtils;
import cn.xshi.common.util.JsonUtil;
import cn.xshi.common.util.StringUtil;
import cn.xshi.log.client.service.LogsUtil;
import cn.xshi.log.model.LogLogin;
import cn.xshi.oauth.util.OauthUtil;
import cn.xshi.oauth.model.OauthAccount;
import cn.xshi.oauth.model.OauthAccountRole;
import cn.xshi.oauth.model.OauthAdminSys;
import cn.xshi.oauth.model.OauthFunctionRole;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.*;
import java.util.List;
/**
 * @Desc 授权中心登录API
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@RestController
@Api(value = "授权中心登录API",tags = "授权中心登录API",description = "授权中心登录API")
@Slf4j
public class OauthLoginController  extends BaseAction {

    @Resource
    private OauthUtil oauthUtil;

    @Resource
    HttpSessionUtils httpSessionUtils;

    @Resource
    private OauthAccountService oauthAccountService;

    @Resource
    private OauthAccountRoleService oauthAccountRoleService;

    @Resource
    private OauthFunctionRoleService oauthFunctionRoleService;

    @Resource
    private OauthAdminService oauthAdminService;

    @Resource
    private OauthAdminSysService oauthAdminSysService;

    @Resource
    LogsUtil logsUtil;

    Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final int WIDTH = 200;// 生成的图片的宽度

    private static final int HEIGHT = 30;// 生成的图片的高度

    /**
     * 登录
     * @param loginEntity
     * @param request
     * @return
     */
    @ApiOperation(value="登录", notes="登录")
    @PostMapping(value="/login")
    @Auth(value = "/login",authenticationType = Auth.AuthorizationType.NOT_REQUIRED_LOGIN)
    public BaseResult login(@RequestBody LoginEntity loginEntity, HttpServletRequest request){
        if(null == loginEntity){
            return outAudStr(false,"登录信息为空");
        }
        if(StringUtil.isEmpty(loginEntity.getAccount())){
            return outAudStr(false,"用户名为空");
        }
        if(StringUtil.isEmpty(loginEntity.getPassword())){
            return outAudStr(false,"密码为空");
        }
        if(!StringUtil.isEmpty(loginEntity.getValidateCode())){
            String rand = httpSessionUtils.getVerifyAttribute(request);
            if(!StringUtils.isEmpty(rand)){
                rand = rand.toLowerCase();
            }
            if(!loginEntity.getValidateCode().equals(rand)){
                return outAudStr(false,"验证码不正确",1);
            }
        }
        LogLogin logLogin = new LogLogin();
        MD5 md5 = new MD5();
        Map<String,Object> condition = new HashMap<>();
        condition.put("account",loginEntity.getAccount());
        condition.put("password",md5.getMD5ofStr(loginEntity.getPassword().trim()));
        OauthAccount oauthAccount = oauthAccountService.login(condition);
        if(null == oauthAccount){
            logLogin.setContent("账号："+loginEntity.getAccount()+"，用户名或密码有误，登录失败");
            logsUtil.loginLogs(logLogin);
            return outAudStr(false,"用户名或密码有误",2);
        }
        if(StringUtil.isEmpty(oauthAccount.getAccountTypeId())){
            logLogin.setContent("账号："+loginEntity.getAccount()+"，该账号未设置账号类型，登录失败");
            logsUtil.loginLogs(logLogin);
            return outAudStr(false,"该账号未设置账号类型",2);
        }
        /* （登录时候废弃判断账号类型是否存在子系统中）
        condition.put("sys_mode_id",oauthSysModeService.getSysModeId(request));
        condition.put("account_type_id",oauthAccount.getAccount_type_id().split(","));
        int count = oauthAccountTypeService.getAccountTypeInSysMode(condition);
        if(count == 0){
            return outAudStr(false,"该账号类型不存在当前子系统",2);
        }*/


        //TODO 处理最后一次登录时间
        oauthAccount.setLastLoginTime(new Date());
        oauthAccountService.updateLoginTime(oauthAccount);

        StringBuffer roleId = new StringBuffer();
        OauthAccountEntity oauthAccountEntity = new OauthAccountEntity();
        BeanUtils.copyProperties(oauthAccount, oauthAccountEntity);


        condition = new HashMap<>();
        condition.put("accountId",oauthAccountEntity.getId());

        //TODO 处理管理员拥有系统范围
        List<OauthAdminSys> oauthAdminSys = adminSys(condition);

        //TODO 处理角色
        List<OauthAccountRole> urList = oauthAccountRoleService.getOauthAccountRoleListByCondition(condition);
        for(int i = 0; i < urList.size(); i++){
            OauthAccountRole oauthAccountRole = urList.get(i);
            if(null != roleId && !StringUtil.isEmpty(roleId.toString())){
                roleId.append(","+oauthAccountRole.getRoleId());
            }else{
                roleId.append(oauthAccountRole.getRoleId());
            }
        }

        //TODO 处理功能
        List<OauthFunctionRole> oauthFunctionRoleList = new ArrayList<OauthFunctionRole>();
        if(!StringUtils.isEmpty(roleId.toString())){
            /////////////根据角色集合查找该用户下所有功能
            condition = new HashMap<String, Object>();
            condition.put("roleId", roleId.toString().split(","));
            oauthFunctionRoleList = oauthFunctionRoleService.getOauthFunctionRoleListByCondition(condition);
        }
        Map<String,String> oauthFunctionInfoUrlMap = new HashMap<>();
        Map<String,String> oauthFunctionInfoMethodMap = new HashMap<>();
        for(OauthFunctionRole oauthFunctionRole:oauthFunctionRoleList){
            oauthFunctionInfoUrlMap.put(oauthFunctionRole.getUrl(),oauthFunctionRole.getUrl());
            oauthFunctionInfoMethodMap.put(oauthFunctionRole.getMethod(),oauthFunctionRole.getMethod());
        }

        BaseHttpSessionEntity baseHttpSessionEntity = new BaseHttpSessionEntity(oauthAccountEntity,roleId.toString(),oauthFunctionInfoUrlMap,oauthFunctionInfoMethodMap,dataAuthority(request,oauthAccountEntity),null, JsonUtil.toFastJson(oauthAdminSys));
        loginEntity.setBaseHttpSessionEntity(JsonUtil.toFastJson(baseHttpSessionEntity));

        String token = oauthUtil.doLastToken(oauthAccount.getId(),loginEntity.getBaseHttpSessionEntity());
        if(StringUtil.isEmpty(token)){//上次Token不存在则重新创建
            Map<String,Object> map = oauthUtil.createTokenFn(oauthAccount.getId(),loginEntity.getBaseHttpSessionEntity(),12);//默认1小时
            if(null != map && !map.isEmpty()){
                token = (String)map.get("Token");
            }
        }
        if(StringUtil.isEmpty(token)){
            logger.debug("-------------未能生成Token信息----------------");
            logLogin.setContent("账号："+loginEntity.getAccount()+"，登录失败");
            logsUtil.loginLogs(logLogin);
            return outAudStr(false,"未能生成Token信息");
        }
        removeVerify(request);
        logger.debug("-------------Token创建成功----------------");
        logLogin.setContent("账号："+loginEntity.getAccount()+"，登录成功");
        logsUtil.loginLogs(logLogin);
        return outAudStr(true,"Login Success，Token创建成功",token);
    }

    /**
     * 处理管理员拥有系统范围
     * @param condition
     * @return
     */
    public List<OauthAdminSys> adminSys(Map<String,Object> condition){
        List<OauthAdmin> oauthAdmins = oauthAdminService.getOauthAdminList(condition);
        List<String> adminIds = new ArrayList<>();
        for(OauthAdmin oauthAdmin:oauthAdmins){
            adminIds.add(oauthAdmin.getId());
        }
        if(null == adminIds || adminIds.isEmpty()){
            return new ArrayList<>();
        }
        condition.put("adminId",adminIds);
        List<OauthAdminSys> oauthAdminSysList = oauthAdminSysService.getOauthAdminSysList(condition);
        MD5 md5 = new MD5();
        for(int i = 0; i < oauthAdminSysList.size(); i++){
            oauthAdminSysList.get(i).setAppSecret(md5.getMD5ofStr(oauthAdminSysList.get(i).getAppSecret()));
        }
        return oauthAdminSysList;
    }

    /**
     * 数据权限
     * @param request
     */
    public List<String> dataAuthority(HttpServletRequest request, OauthAccountEntity oauthAccountEntity){
        /////////////////////////////////
        /////////////////////////操作数据及数据功能权限 开始
        /////////////////////////////////
//        Map<String,Object> condition = new HashMap<String, Object>();
//
//        if(!isAdmin(oauthAccountEntity)){
//            condition.put("xt_userinfo_id", oauthAccountEntity.getAccount_id());
//        }
        List<String> systemUandM = new ArrayList<String>();//用户及功能URL
//        List<XtDataAuthority> xt_Data_AuthorityList = xtDataAuthorityService.getXtDataAuthorityListForLogin(condition);
//        for(XtDataAuthority xtDataAuthority :xt_Data_AuthorityList){
//            systemUandM.add(xtDataAuthority.getCurrentAccountId()+"#"+xtDataAuthority.getXt_functioninfoURL());
//        }
//        //将数据及数据功能权限等信息放入到里面
//        /////////////////////////////////
//        /////////////////////////操作数据及数据功能权限 结束
//        /////////////////////////////////
        return systemUandM;
    }

    /**
     * 注销
     * @param request
     */
    @ApiOperation(value="注销", notes="注销")
    @PostMapping(value="/loginOut")
    @Auth(value = "/loginOut",authenticationType = Auth.AuthorizationType.NOT_REQUIRED_LOGIN)
    public BaseResult loginOut(HttpServletRequest request){
        String token = oauthUtil.getTokenId(request);
        OauthAccountEntity oauthAccountEntity = getCurrentAccountInfo();
        oauthUtil.destory(request);
        if(null != oauthAccountEntity){
            LogLogin logLogin = new LogLogin();
            logLogin.setContent("账号："+oauthAccountEntity.getAccount()+"，注销平台成功");
            logsUtil.loginLogs(logLogin);
        }
        return outAudStr(true, "注销平台成功");
    }

    /**
     * 创建SessionId
     * @param request
     */
    @ApiOperation(value="创建SessionId", notes="创建SessionId")
    @GetMapping(value="/JSessionId")
    @Auth(value = "/JSessionId",authenticationType = Auth.AuthorizationType.NOT_REQUIRED_LOGIN)
    public BaseResult GenJSessionId(HttpServletRequest request){
        String sessionId = httpSessionUtils.getSessionId(request);
        return new BaseResult("Create JSessionId success",true,sessionId);
    }

    /**
     *
     * @param random
     * @param sessionId
     * @return
     */
    public BaseResult verify(String random,String sessionId){
       httpSessionUtils.setAttributeExpTime(SessionConstant.VERIFY_STORE_PATH+sessionId, random,1);//5分钟
        return new BaseResult("Create verify success",true,sessionId);
    }

    /**
     * @param request
     * @return
     */
    @ApiOperation(value="查询验证码", notes="查询验证码")
    @GetMapping(value="/query/verify")
    @Auth(value = "/query/verify",authenticationType = Auth.AuthorizationType.NOT_REQUIRED_LOGIN)
    public BaseResult queryVerify(HttpServletRequest request){
        String rand = httpSessionUtils.getVerifyAttribute(request);
        return new BaseResult("Query verify success",true,rand);
    }

    /**
     *
     * @param request
     */
    public void removeVerify(HttpServletRequest request){
        httpSessionUtils.del(SessionConstant.VERIFY_STORE_PATH+httpSessionUtils.getSessionId(request));
    }

    /**
	 *
	 * @param request
	 * @param response
	 * @return
	 */
    @ApiOperation(value="创建验证码", notes="创建验证码")
	@GetMapping(value="/verify")
    @Auth(value = "/verify",authenticationType = Auth.AuthorizationType.NOT_REQUIRED_LOGIN)
    public void verify(HttpServletRequest request,HttpServletResponse response){
		// 设置响应头通知浏览器以图片的形式打开
		response.setContentType("image/jpeg");// 等同于response.setHeader("Content-Type",
		// 设置响应头控制浏览器不要缓存
		response.setDateHeader("expries", -1);
		response.setHeader("Cache-Control", "no-cache");
		response.setHeader("Pragma", "no-cache");

		// 1.在内存中创建一张图片
		BufferedImage image = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
		// 2.虚拟画笔得到图片
		Graphics g = image.getGraphics();
		// 3.设置图片的背影色
		setBackGround(g);
		// 4.设置图片的边框
		setBorder(g);
		// 5.在图片上画干扰线
//		drawRandomLine(g);
		// 6.写在图片上随机数
		String random = drawRandomNum((Graphics2D) g);// 生成数字和字母组合的验证码图片
        String sessionId = request.getParameter("sessionId");
        verify(random,sessionId);
		try {
			ImageIO.write(image, "jpg", response.getOutputStream());
			log.info("生成验证码结束");
		} catch (IOException e) {
			log.error("生成验证码出现异常");
		}
	}

	/**
	 * 设置图片的背景色
	 * @param g
	 */
	private void setBackGround(Graphics g) {
		// 设置颜色
		g.setColor(Color.WHITE);
		// 填充区域
		g.fillRect(0, 0, WIDTH, HEIGHT);
	}

	/**
	 * 设置图片的边框
	 * @param g
	 */
	private void setBorder(Graphics g) {
		// 设置边框颜色
		g.setColor(Color.WHITE);
		// 边框区域
		g.drawRect(1, 1, WIDTH - 2, HEIGHT - 2);
	}

	/**
	 * 在图片上画随机线条
	 * @param g
	 */
	private void drawRandomLine(Graphics g) {
		// 设置颜色
//		g.setColor(Color.GREEN);
		Random r=new Random();
		// 设置线条个数并画线
		for (int i = 0; i < 10; i++) {
			int x1 = r.nextInt(WIDTH);
			int y1 = r.nextInt(HEIGHT);
			int x2 = r.nextInt(WIDTH);
			int y2 = r.nextInt(HEIGHT);
			g.drawLine(x1, y1, x2, y2);
			//设置干扰线颜色
			Color color = new Color(20 + r.nextInt(210), 20 + r.nextInt(210), 20 + r.nextInt(210));
			g.setColor(color);
		}

	}

	/**
	 * 画随机字符
	 * @param g
	 */
	private String drawRandomNum(Graphics2D g) {
		// 设置颜色
		g.setColor(Color.RED);
		// 设置字体
		g.setFont(new Font("宋体", Font.BOLD, 30));

		// 数字和字母的组合
//		String baseNumLetter = "Aa0Bb1CcDd3EeFf5Gg6HhJjKkLl7MmN9nOoPp8QqRrSs2TtUuVv4WwXxYyZz";
		String baseNumLetter = "0123456789";
		return createRandomChar(g, baseNumLetter);
	}

	/**
	 * 创建随机字符
	 * @param g
	 * @param baseChar
	 * @return 随机字符
	 */
	private String createRandomChar(Graphics2D g, String baseChar) {
		StringBuffer sb = new StringBuffer();
		Random r=new Random();
		int x = 5;
		String ch = "";
		// 控制字数
		for (int i = 0; i < 6; i++) {
			// 设置字体旋转角度
			int degree = r.nextInt() % 30;
			ch = baseChar.charAt(new Random().nextInt(baseChar.length())) + "";
			//设置随机数的颜色
			Color color = new Color(20 + r.nextInt(210), 20 + r.nextInt(210), 20 + r.nextInt(210));
			g.setColor(color);
			sb.append(ch);
			// 正向角度
			g.rotate(degree * Math.PI / 180, x, 30);
			g.drawString(ch, x, 20);
			// 反向角度
			g.rotate(-degree * Math.PI / 180, x, 30);
			x += 30;
		}
		return sb.toString();
	}
}
